package com.rambler.extension.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rambler.api.fileupload.FileUploadProxy;
import com.rambler.api.fileupload.dto.FileUploadDTO;
import com.rambler.api.fileupload.dto.ImageProcessOption;
import com.rambler.api.fileupload.vo.FileUploadVO;
import com.rambler.common.entity.BaseEntity;
import com.rambler.common.response.CommonResponse;
import com.rambler.common.utils.IDUtil;
import com.rambler.common.utils.URLUtil;
import com.rambler.extension.converters.ExtBookmarkConverter;
import com.rambler.extension.converters.ExtBookmarkPropConverter;
import com.rambler.extension.dto.ExtBookmarkDTO;
import com.rambler.extension.entity.ExtBookmark;
import com.rambler.extension.entity.ExtBookmarkProp;
import com.rambler.extension.entity.ExtSiteIcon;
import com.rambler.extension.mapper.ExtBookmarkMapper;
import com.rambler.extension.mapper.ExtBookmarkPropMapper;
import com.rambler.extension.mapper.ExtSiteIconMapper;
import com.rambler.extension.vo.ExtBookmarkVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * BookmarkService
 * 提供书签的增删改查业务逻辑处理
 *
 * @author suhao
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ExtBookmarkService extends ServiceImpl<ExtBookmarkMapper, ExtBookmark> {

    @Resource
    private ExtBookmarkConverter bookmarkConverter;

    @Resource
    private ExtBookmarkPropConverter bookmarkPropConverter;

    @Resource
    private ExtBookmarkPropMapper bookmarkPropMapper;

    @Resource
    private FileUploadProxy fileUploadProxy;

    @Resource
    private ExtSiteIconMapper siteIconMapper;

    /**
     * 根据书签 ID 查询详细信息
     *
     * @param id 书签唯一标识
     * @return 查询成功返回书签 VO，未找到返回失败响应
     */
    public CommonResponse<ExtBookmarkVO> queryById(String id) {
        ExtBookmark bookmark = getById(id);
        if (bookmark == null) {
            return CommonResponse.failure("未找到对应的书签");
        }
        ExtBookmarkVO vo = bookmarkConverter.toVO(bookmark);
        return CommonResponse.success(vo);
    }

    /**
     * 根据用户 ID 查询该用户的所有书签
     *
     * @param dto 包含查询条件的 DTO，当前仅支持按 userId 查询
     * @return 返回用户的书签列表
     */
    public CommonResponse<List<ExtBookmarkVO>> queryBookmarksByDTO(ExtBookmarkDTO dto) {
        LambdaQueryWrapper<ExtBookmark> queryWrapper = new LambdaQueryWrapper<>();
        if (dto == null || dto.getUserId() == null) {
            return CommonResponse.failure("缺少用户ID参数");
        }
        queryWrapper.eq(ExtBookmark::getUserId, dto.getUserId());
        List<ExtBookmark> bookmarks = list(queryWrapper);
        List<ExtBookmarkVO> bookmarkVoS = bookmarkConverter.toVOList(bookmarks);
        // 查询书签props
        List<String> ids = bookmarks.stream().map(BaseEntity::getId).toList();
        // 查询书签props
        if (!ids.isEmpty()) {
            LambdaQueryWrapper<ExtBookmarkProp> propWrapper = new LambdaQueryWrapper<>();
            propWrapper.in(ExtBookmarkProp::getBookmarkId, ids);
            List<ExtBookmarkProp> extBookmarkProps = bookmarkPropMapper.selectList(propWrapper);
            // 转为map，key为书签id，value为书签的props
            Map<String, List<ExtBookmarkProp>> bookmarkPropMap = extBookmarkProps.stream().collect(Collectors.groupingBy(ExtBookmarkProp::getBookmarkId));
            bookmarkVoS.forEach(bookmark -> bookmark.setProps(bookmarkPropConverter.toVOList(bookmarkPropMap.get(bookmark.getId()))));
        }
        return CommonResponse.success(bookmarkVoS);
    }

    /**
     * 根据 ID 删除书签
     *
     * @param id 要删除的书签 ID
     * @return 删除成功返回 success，否则返回失败信息
     */
    public CommonResponse<Void> deleteBookmark(String id) {
        if (getById(id) == null) {
            return CommonResponse.failure("书签不存在，无法删除");
        }
        boolean removed = removeById(id);
        return removed ? CommonResponse.success() : CommonResponse.failure("删除书签失败");
    }

    /**
     * 创建新的书签
     *
     * @param bookmarkDTO 提交的书签数据
     * @return 创建成功后返回新的书签信息
     */
    public CommonResponse<ExtBookmarkVO> createBookmark(ExtBookmarkDTO bookmarkDTO) {
        if (bookmarkDTO == null) {
            return CommonResponse.failure("请求体不能为空");
        }

        ExtBookmark bookmark = bookmarkConverter.toEntity(bookmarkDTO);
        // 可设置默认值，例如创建时间
        bookmark.setCreateTime(new Date());

        boolean saved = save(bookmark);
        ExtBookmarkVO bookmarkVO = bookmarkConverter.toVO(bookmark);
        return saved ? CommonResponse.success(bookmarkVO) : CommonResponse.failure("保存书签失败");
    }

    /**
     * 更新现有书签
     *
     * @param bookmarkDTO 包含书签 ID 及需修改字段
     * @return 更新成功返回修改后的书签信息
     */
    public CommonResponse<ExtBookmarkVO> editBookmark(ExtBookmarkDTO bookmarkDTO) {
        if (bookmarkDTO == null || bookmarkDTO.getId() == null) {
            return CommonResponse.failure("更新必须提供书签ID");
        }

        if (getById(bookmarkDTO.getId()) == null) {
            return CommonResponse.failure("待更新的书签不存在");
        }

        ExtBookmark bookmark = bookmarkConverter.toEntity(bookmarkDTO);
        bookmark.setUpdateTime(new Date());
        boolean updated = updateById(bookmark);
        ExtBookmarkVO bookmarkVO = bookmarkConverter.toVO(bookmark);
        return updated ? CommonResponse.success(bookmarkVO) : CommonResponse.failure("更新书签失败");
    }

    /**
     * 上传书签图标
     * 用户不需要关注上传路径, 只需要上传文件
     *
     * @param file 图标文件
     * @return 文件信息
     */
    public CommonResponse<FileUploadVO> uploadBookmarkIcon(MultipartFile file, String url) {
        // 1️ 获取url的主机名
        String host = URLUtil.extractHost(url);

        // 2️ 判断ext_site_icon是否存在记录
        LambdaQueryWrapper<ExtSiteIcon> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ExtSiteIcon::getHost, host);
        ExtSiteIcon siteIcon = siteIconMapper.selectList(queryWrapper).stream().findFirst().orElse(null);

        // 3️ 如果存在, 根据id查询到文件信息并返回
        if (siteIcon != null) {
            String fileId = siteIcon.getIconId();
            return fileUploadProxy.selectById(fileId);
        }
        // 4️ 如果不存在, 上传返回文件信息
        FileUploadDTO fileUploadDTO = new FileUploadDTO();
        fileUploadDTO.setUploadType("oss");
        fileUploadDTO.setIsPublic(1);
        fileUploadDTO.setImageProcessOption(new ImageProcessOption("webp", 0.9f, null, new ImageProcessOption.ResizeOption(128, 128)));
        CommonResponse<FileUploadVO> uploadResult = fileUploadProxy.upload(file, "all-in-one-hot/extension/icons", "oss", "1", "webp", "0.9", null, "128,128");
        if (uploadResult.getCode() == 200) {
            // 5️ 保存到ext_site_icon中
            FileUploadVO uploadInfo = uploadResult.getData();
            ExtSiteIcon saveInfo = new ExtSiteIcon();
            saveInfo.setId(IDUtil.randomUUID());
            saveInfo.setHost(host);
            saveInfo.setIconUrl(url);
            saveInfo.setIconId(uploadInfo.getFileKey());
            siteIconMapper.insert(saveInfo);
            return CommonResponse.success(uploadInfo);
        } else {
            return CommonResponse.failure(uploadResult.getMessage());
        }
    }
}
